package com.hrm.websocket;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;

import org.apache.catalina.Session;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.simple.JSONObject;

import cn.test.protocol.ProtocolImpl;

public class WebSocketSession {
	private static final Log log = LogFactory.getLog(WebSocketSession.class);
	SocketChannel socketChannel;
	private ByteBuffer readBuffer;
	private ByteBuffer writeBuffer;
	private boolean connected;

	private WebSocketUtil webSocketUtil;
	private ProtocolImpl protocolImpl;
	private String validCode;
	private String pid;
	private boolean isWriteBianry=false;//是否正在读写二进制文件
	private String fileType;//上传的文件类型
	private String filePath;//上传的文件路径
	private String fileName;//上传后生成的文件名
	private JSONObject jo;//上传文件的上一次请求消息
	
	public JSONObject getJo() {
		return jo;
	}
	public void setJo(JSONObject jo) {
		this.jo = jo;
	}
	public String getFileType() {
		return fileType;
	}
	public void setFileType(String fileType) {
		this.fileType = fileType;
	}
	public String getFilePath() {
		return filePath;
	}
	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}
	public String getFileName() {
		return fileName;
	}
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}
	public boolean isWriteBianry() {
		return isWriteBianry;
	}
	public void setWriteBianry(boolean isWriteBianry) {
		this.isWriteBianry = isWriteBianry;
	}
	private int dataTotalLength;//当前消息传输的数据总长度
	private int writeLength;//已写入的文件长度
	private long uploadFileSize;//上传文件的总大小
	private long uploadedSize;//文件已上传的大小
	
	public long getUploadedSize() {
		return uploadedSize;
	}
	public void setUploadedSize(long uploadedSize) {
		this.uploadedSize = uploadedSize;
	}
	public long getUploadFileSize() {
		return uploadFileSize;
	}
	public void setUploadFileSize(long uploadFileSize) {
		this.uploadFileSize = uploadFileSize;
	}
	public int getWriteLength() {
		return writeLength;
	}
	public void setWriteLength(int writeLength) {
		this.writeLength = writeLength;
	}
	public int getDataTotalLength() {
		return dataTotalLength;
	}
	public void setDataTotalLength(int dataTotalLength) {
		this.dataTotalLength = dataTotalLength;
	}
	private List<Object> offLineMessage;
	/**
	 * 每次通信的消息长度，据此判断当前消息是否为连续消息，
	 * 若此长度大于当前readbuffer读取的数据长度，则直接读取，否则需要做数据解析
	 */
	private int msgLength;
	public int getMsgLength() {
		return msgLength;
	}
	public void setMsgLength(int msgLength) {
		this.msgLength = msgLength;
	}
	private byte[] maskKey=new byte[4];
	public byte[] getMaskKey() {
		return maskKey;
	}
	public void setMaskKey(byte[] maskKey) {
		this.maskKey = maskKey;
	}
	
	public WebSocketSession(SocketChannel socketChannel) {
		this.socketChannel = socketChannel;
		readBuffer = ByteBuffer.allocate(1024*512);
		writeBuffer = ByteBuffer.allocate(1024*512);
		connected = false;
		webSocketUtil=new WebSocketUtil();
		protocolImpl=new ProtocolImpl();
		offLineMessage=new ArrayList<Object>();
	}
	public WebSocketSession(SocketChannel socketChannel,ProtocolImpl protocolImpl) {
		this.socketChannel = socketChannel;
		readBuffer = ByteBuffer.allocate(1024*100);
		writeBuffer = ByteBuffer.allocate(1024*100);
		connected = false;
		webSocketUtil=new WebSocketUtil();
		this.protocolImpl=protocolImpl;
		offLineMessage=new ArrayList<Object>();
	}

	public ByteBuffer getReadBuffer() {
		return readBuffer;
	}
	public void setReadBuffer(ByteBuffer readBuffer) {
		this.readBuffer = readBuffer;
	}
	public boolean read() {
		readBuffer.clear();
		int readNum = 0;
		try {
			readNum = socketChannel.read(readBuffer);
		} catch (IOException e) {
			readBuffer.clear();
			log.info("session read data has exception ,session will closed!");
			e.printStackTrace();
			return false;
		}
		if (readNum == -1) {
			log.info("session read data num is -1 ,session will closed!");
			readBuffer.clear();
			return false;
		} else if (readNum > 0) {
			readBuffer.flip();
			if (connected) {
				//解析协议
				try{
					byte[] data=webSocketUtil.parseWebSocketData(this,readBuffer);
					if(data==null){
						return true;
					}
					if(this.getUploadedSize()>0&&this.getUploadedSize()<this.getUploadFileSize()){//如果文件未上传成功，则发送进度消息回客户端
						send(data);
						return true;
					}
					//如果是上传文件的socket通信，则不解析数据消息，直接发送文件路径到from端
					String msg=new String(data);
					log.debug(msg);
					String ret=protocolImpl.parse(msg,this);
					send(ret.getBytes());
				}catch(Exception e){
					e.printStackTrace();
				}
			} else {
				connect();
			}
		}
		return true;
	}

	public void close() {
		readBuffer.clear();
		readBuffer = null;
		writeBuffer.clear();
		writeBuffer = null;
		try {
			socketChannel.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void send(byte[] bytes) {
		byte[] data = null;
		int length = bytes.length;
		if (length < 126) {
			data = new byte[bytes.length + 2];
			data[0] = (byte) 129;
			data[1] = (byte) bytes.length; // 消息长度不大亄1�76的情冄1�7
			System.arraycopy(bytes, 0, data, 2, bytes.length);
		} else if (length < 65535) {
			data = new byte[bytes.length + 4];
			data[0] = (byte) 129;
			data[1] = (byte) 126; // 消息长度不大亄1�76的情冄1�7
			data[2] = (byte) ((length & 0xff00) >> 8); // 取第丄1�7个字节，10进制轄1�7�制，int轄1�7�无符号16进制敄1�7
			data[3] = (byte) (length & 0x00ff);
			System.arraycopy(bytes, 0, data, 4, bytes.length);
		} else {
			// 超长情况不做处理
			System.out.println("返回结果太长，超迄1�7535个字节�1�7�1�7");
		}

		writeBuffer.clear();
		writeBuffer.put(data);
		writeBuffer.flip();
		try {
			socketChannel.write(writeBuffer);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void connect() {
		String msg = new String(readBuffer.array(), 0, readBuffer.limit());
//		System.out.println(msg);
		int keyIndex = msg.indexOf("Sec-WebSocket-Key:") + 18;
		String key = msg.substring(keyIndex, msg.indexOf("\n", keyIndex));
		if (key != null && !key.trim().equals("")) {
			key = key.trim();
			writeBuffer.clear();
			writeBuffer.put(webSocketUtil.warpConnectMessage(key)
					.getBytes());
			writeBuffer.flip();
			connected = true;
			try {
				socketChannel.write(writeBuffer);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
//		send("connect success".getBytes());
	}

	public String getValidCode() {
		return validCode;
	}

	public void setValidCode(String validCode) {
		this.validCode = validCode;
	}

	public String getPid() {
		return pid;
	}

	public void setPid(String pid) {
		this.pid = pid;
	}
	
	public List<Object> getOffLineMessage() {
		return offLineMessage;
	}

	public void setOffLineMessage(List<Object> offLineMessage) {
		this.offLineMessage = offLineMessage;
	}


}
